﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Collections;
using System.Text;
using System.Linq.Expressions;
using System.Web.Mvc.Html;
using System.Reflection;
using System.Web.Routing;
using System.Data.Objects.DataClasses;

namespace System.Web.Mvc
{
    public class TreeViewNode
    {
        public TreeViewNode(string _parentid, string _nodeid, string _text, string _value = null, string _url = null, bool _haschild = true, bool _isgroup = true, bool _isopen = true)
        {
            parentid = _parentid;
            text = _text;
            if (string.IsNullOrEmpty(value))
            {
                value = text;
            }
            nodeid = _nodeid;
            value = _value;
            url = _url;
            isgroup = _isgroup;
            haschild = _haschild;
            isopen = _isopen;
        }
        public string nodeid;
        public string parentid;
        public string text;
        public string value;
        public string url;
        public bool isgroup;
        public bool haschild;
        public bool isopen;
    }

    public static class MVCHelpers
    {
        #region Html.Table(name, items, attributes)
        public static string Table(this HtmlHelper helper, string name, IList items, IDictionary<string, object> attributes)
        {
            if (items == null || items.Count == 0 || string.IsNullOrEmpty(name))
            {
                return string.Empty;
            }

            return BuildTable(name, items, attributes);
        }

        private static string BuildTable(string name, IList items, IDictionary<string, object> attributes)
        {
            StringBuilder sb = new StringBuilder();
            BuildTableHeader(sb, items[0].GetType());

            foreach (var item in items)
            {
                BuildTableRow(sb, item);
            }

            TagBuilder builder = new TagBuilder("table");
            builder.MergeAttributes(attributes);
            builder.MergeAttribute("name", name);
            builder.InnerHtml = sb.ToString();
            return builder.ToString(TagRenderMode.Normal);
        }

        private static void BuildTableRow(StringBuilder sb, object obj)
        {
            Type objType = obj.GetType();
            sb.AppendLine("\t<tr>");
            foreach (var property in objType.GetProperties())
            {
                sb.AppendFormat("\t\t<td>{0}</td>\n", property.GetValue(obj, null));
            }
            sb.AppendLine("\t</tr>");
        }

        private static void BuildTableHeader(StringBuilder sb, Type p)
        {
            sb.AppendLine("\t<tr>");
            foreach (var property in p.GetProperties())
            {
                sb.AppendFormat("\t\t<th>{0}</th>\n", property.Name);
            }
            sb.AppendLine("\t</tr>");
        }
        #endregion

        #region Html.Tree()

        public static MvcHtmlString Tree<TModel>(this HtmlHelper<TModel> Html, IEnumerable<TreeViewNode> lists, int level = 1, string treeviewid = "treeview", string parentColumn = "parentid", string idColumn = "nodeid", string rootid = "", string textColumn = "display", string valueColumn = "value")
        {
            int nodecount = 0;
            int currentlevel = 0;
            var list = lists.Where(x => x.parentid == rootid);
            TagBuilder ultag = new TagBuilder("ul");
            ultag.Attributes.Add("class", "treeview");
            ultag.Attributes.Add("id", treeviewid);
            ultag.InnerHtml += BuildChildNode(lists, treeviewid, rootid, parentColumn, textColumn, valueColumn, level - 1, ref nodecount, currentlevel);
            string html = ultag.ToString();
            return new MvcHtmlString(ultag.ToString());
        }

        private static string BuildChildNode(IEnumerable<TreeViewNode> lists, string treeid, string parentid, string parentColumn, string textColumn, string valueColumn, int level, ref int nowcount, int nowlevel)
        {
            string subhtml = "";
            int inlevelcount = 1;
            var repeatlist = lists.Where(x => x.parentid == parentid);
            int inleveltotal = repeatlist.Count();
            if (level >= 0)
            {
                foreach (var item in repeatlist)
                {
                    var list = lists.Where(x => x.parentid == item.nodeid);
                    TagBuilder litag = new TagBuilder("li");
                    litag.Attributes.Add("class", "level" + nowlevel);
                    litag.Attributes.Add("id", treeid + "_" + nowcount);
                    TagBuilder btn01 = new TagBuilder("button");
                    btn01.Attributes.Add("class", "switch center_open level" + nowlevel);
                    btn01.Attributes.Add("id", treeid + "_" + nowcount + "_switch");
                    //TagBuilder btn02 = new TagBuilder("button");
                    TagBuilder a01 = new TagBuilder("a");
                    a01.Attributes.Add("class", "level" + nowlevel);
                    a01.Attributes.Add("id", treeid + "_" + nowcount + "_a");
                    if (!string.IsNullOrEmpty(item.url))
                    {
                        a01.Attributes.Add("openurl", item.url);
                    }
                    TagBuilder btn03 = new TagBuilder("button");
                    btn03.Attributes.Add("class", "ico_close");
                    btn03.Attributes.Add("id", treeid + "_" + nowcount + "_ico");
                    TagBuilder span01 = new TagBuilder("span");
                    span01.Attributes.Add("id", treeid + "_" + nowcount + "_span");
                    span01.InnerHtml = item.text;
                    a01.InnerHtml = btn03.ToString() + span01.ToString();
                    TagBuilder ul01 = new TagBuilder("ul");
                    ul01.Attributes.Add("class", "line level" + nowlevel);
                    ul01.Attributes.Add("id", treeid + "_" + nowcount + "_ul");
                    if (level != 0)
                    {
                        if (inlevelcount == 1 && nowcount == 0)
                        {
                            btn01.MergeAttribute("class", "switch roots_open level" + nowlevel, true);
                            btn03.MergeAttribute("class", "ico_close", true);
                        }
                        if (inlevelcount == inleveltotal)
                        {
                            btn01.MergeAttribute("class", "switch bottom_open level" + nowlevel, true);
                            btn03.MergeAttribute("class", "ico_close", true);
                            ul01.MergeAttribute("class", "level" + nowlevel, true);
                        }
                    }
                    else
                    {
                        if (inlevelcount == inleveltotal)
                        {
                            btn01.MergeAttribute("class", "switch bottom_close level" + nowlevel, true);
                        }
                        else
                        {
                            btn01.MergeAttribute("class", "switch center_close level" + nowlevel, true);
                        }
                        if (inlevelcount == 1 && nowcount == 0)
                        {
                            btn01.MergeAttribute("class", "switch roots_close level" + nowlevel, true);
                        }
                    }

                    nowcount++;
                    ul01.InnerHtml += BuildChildNode(lists, treeid, item.nodeid, parentColumn, textColumn, valueColumn, level - 1, ref nowcount, nowlevel + 1);
                    litag.InnerHtml += btn01.ToString() + a01.ToString() + ul01.ToString();
                    subhtml += litag.ToString();
                    inlevelcount++;
                }
                return subhtml;
            }
            else
            {
                return "";
            }
        }

        #endregion

        #region Html.TextBoxRequired(id, errMsg, style, value)
        public static MvcHtmlString TextBoxRequired<TModel>(this HtmlHelper<TModel> htmlHelper, string textboxId, string errorMessage, string styleString, string valueString = null)
        {
            TagBuilder builder = new TagBuilder("input");
            builder.MergeAttribute("type", "text");
            builder.MergeAttribute("style", styleString);
            builder.MergeAttribute("name", textboxId);
            builder.MergeAttribute("id", textboxId);
            builder.MergeAttribute("data-val-required", errorMessage);
            builder.MergeAttribute("data-val", "true");
            if (!string.IsNullOrEmpty(valueString))
                builder.MergeAttribute("value", valueString);
            MvcHtmlString mhs = new MvcHtmlString(builder.ToString());
            return mhs;
        }
        #endregion

        #region Html.ImgAjaxUpload(id, errMsg, style, value)
        public static MvcHtmlString ImgAjaxUpload<TModel>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, String>> expression, string uploadMethod = null, string className = "upload")
        {
            ModelMetadata metadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);

            TagBuilder divTag = new TagBuilder("div");
            divTag.AddCssClass(className);
            TagBuilder imgTag = new TagBuilder("img");
            imgTag.MergeAttribute("id", metadata.PropertyName + "_img");
            imgTag.MergeAttribute("name", metadata.PropertyName + "_img");
            if (metadata.Model != null)
            {
                imgTag.MergeAttribute("src", metadata.Model.ToString());
            }
            TagBuilder fileInput = new TagBuilder("input");
            fileInput.MergeAttribute("type", "file");
            fileInput.MergeAttribute("name", metadata.PropertyName + "_filePath");
            fileInput.MergeAttribute("id", metadata.PropertyName + "_filePath");
            TagBuilder buttonInput = new TagBuilder("input");
            buttonInput.MergeAttribute("type", "button");
            buttonInput.MergeAttribute("onclick", uploadMethod);
            buttonInput.MergeAttribute("name", metadata.PropertyName + "_uploadButton");
            buttonInput.MergeAttribute("id", metadata.PropertyName + "_uploadButton");
            buttonInput.MergeAttribute("fileid", metadata.PropertyName + "_filePath");
            buttonInput.MergeAttribute("imgid", metadata.PropertyName + "_img");
            buttonInput.MergeAttribute("saveid", metadata.PropertyName);
            buttonInput.MergeAttribute("value", "上传");
            divTag.InnerHtml = imgTag.ToString() + "<br />" + fileInput.ToString() + buttonInput.ToString() + htmlHelper.HiddenFor(expression);
            MvcHtmlString mhs = new MvcHtmlString(divTag.ToString());
            return mhs;
        }

        public static MvcHtmlString ImgAjaxUploadView<TModel>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, String>> expression, string className = "upload")
        {
            ModelMetadata metadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);
            TagBuilder divTag = new TagBuilder("div");
            divTag.AddCssClass(className);
            TagBuilder imgTag = new TagBuilder("img");
            imgTag.MergeAttribute("id", metadata.PropertyName + "_img");
            imgTag.MergeAttribute("name", metadata.PropertyName + "_img");
            if (metadata.Model != null)
            {
                imgTag.MergeAttribute("src", metadata.Model.ToString());
            }
            divTag.InnerHtml = imgTag.ToString() + "<br />";
            MvcHtmlString mhs = new MvcHtmlString(divTag.ToString());
            return mhs;
        }
        #endregion

        #region Html.FileAjaxUpload(id, errMsg, style, value)
        public static MvcHtmlString FileAjaxUpload<TModel>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, String>> expression, string uploadMethod, string className = "upload")
        {
            ModelMetadata metadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);
            TagBuilder divTag = new TagBuilder("div");
            divTag.AddCssClass(className);
            TagBuilder aTag = new TagBuilder("a");
            aTag.MergeAttribute("name", metadata.PropertyName + "_show");
            aTag.MergeAttribute("id", metadata.PropertyName + "_show");
            aTag.MergeAttribute("target", "_blank");
            string fileurl = "";
            if (metadata.Model != null)
            {
                string filepath = metadata.Model.ToString();
                aTag.MergeAttribute("href", filepath);
                aTag.InnerHtml = filepath.Substring(filepath.LastIndexOf("/") + 1);
            }
            fileurl = aTag.ToString() + "<br />";
            TagBuilder fileInput = new TagBuilder("input");
            fileInput.MergeAttribute("type", "file");
            fileInput.MergeAttribute("name", metadata.PropertyName + "_filePath");
            fileInput.MergeAttribute("id", metadata.PropertyName + "_filePath");
            TagBuilder buttonInput = new TagBuilder("input");
            buttonInput.MergeAttribute("type", "button");
            buttonInput.MergeAttribute("onclick", uploadMethod);
            buttonInput.MergeAttribute("name", metadata.PropertyName + "_uploadButton");
            buttonInput.MergeAttribute("id", metadata.PropertyName + "_uploadButton");
            buttonInput.MergeAttribute("fileid", metadata.PropertyName + "_filePath");
            buttonInput.MergeAttribute("showid", metadata.PropertyName + "_show");
            buttonInput.MergeAttribute("saveid", metadata.PropertyName);
            buttonInput.MergeAttribute("value", "上传");
            divTag.InnerHtml = fileurl + fileInput.ToString() + buttonInput.ToString() + htmlHelper.HiddenFor(expression);
            MvcHtmlString mhs = new MvcHtmlString(divTag.ToString());
            return mhs;
        }

        public static MvcHtmlString FileAjaxUploadView<TModel>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, String>> expression, string className = "upload")
        {
            ModelMetadata metadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);
            TagBuilder divTag = new TagBuilder("div");
            divTag.AddCssClass(className);
            TagBuilder aTag = new TagBuilder("a");
            aTag.MergeAttribute("name", metadata.PropertyName + "_show");
            aTag.MergeAttribute("id", metadata.PropertyName + "_show");
            aTag.MergeAttribute("target", "_blank");
            string fileurl = "";
            if (metadata.Model != null)
            {
                string filepath = metadata.Model.ToString();
                aTag.MergeAttribute("href", filepath);
                aTag.InnerHtml = filepath.Substring(filepath.LastIndexOf("/") + 1);
            }
            fileurl = aTag.ToString();
            divTag.InnerHtml = fileurl;
            MvcHtmlString mhs = new MvcHtmlString(divTag.ToString());
            return mhs;
        }
        #endregion

        #region Html.TextBoxForDate(x => x.field, class)

        public static MvcHtmlString TextBoxForDateYM<TModel>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, DateTime?>> expression, string format = "yyyy-MM", object htmlAttributes = null, string className = "datepicker-ym")
        {
            return htmlHelper.TextBoxForDate(expression, format, htmlAttributes, className);
        }

        public static string DisplayForDateYM<TModel>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, DateTime?>> expression, string format = "yyyy-MM", object htmlAttributes = null)
        {
            return htmlHelper.DisplayForDate(expression, format, htmlAttributes);
        }

        public static MvcHtmlString TextBoxForDate<TModel>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, DateTime?>> expression, string format = "yyyy-MM-dd", object htmlAttributes = null, string className = "datepicker")
        {
            ModelMetadata metadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);
            TagBuilder builder = new TagBuilder("input");
            if (!string.IsNullOrEmpty(className))
                builder.MergeAttribute("class", className);
            builder.MergeAttribute("type", "text");
            Nullable<DateTime> time = (Nullable<DateTime>)metadata.Model;
            builder.MergeAttribute("class", className);
            builder.MergeAttribute("name", metadata.PropertyName);
            builder.MergeAttribute("id", metadata.PropertyName);
            builder.MergeAttribute("readonly", "readonly");
            var @value = (DateTime?)metadata.Model;
            if (@value.HasValue)
                builder.MergeAttribute("value", @value.Value.ToString(format));
            builder.MergeAttributes<string, object>(htmlHelper.GetUnobtrusiveValidationAttributes(ExpressionHelper.GetExpressionText(expression), metadata));
            builder.MergeAttributes<string, object>(((IDictionary<string, object>)HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes)));
            MvcHtmlString mhs = new MvcHtmlString(builder.ToString());
            return mhs;
        }

        public static string DisplayForDate<TModel>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, DateTime?>> expression, string format = "yyyy-MM-dd", object htmlAttributes = null)
        {
            ModelMetadata metadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);
            var @value = (DateTime?)metadata.Model;
            string mhs = "-";
            if (@value.HasValue)
                mhs = @value.Value.ToString(format);
            return mhs;
        }
        #endregion

        #region Html.CheckBoxListFor [4 overrides]

        public static MvcHtmlString CheckBoxListFor<TModel>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, String>> expression, string labelClass = "checklabel")
        {
            //ModelMetadata metadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);
            //string className = Guid.NewGuid().ToString();
            //string clickAction = "setCheckBoxListValue('" + className + "', '" + metadata.PropertyName + "')";
            //string html = "";
            //try
            //{
            //    string[] vals = metadata.Model.ToString().Split(',');
            //    TagBuilder nobr = new TagBuilder("nobr");
            //    foreach (var item in lists)
            //    {
            //        TagBuilder builder = new TagBuilder("input");
            //        builder.MergeAttribute("type", "checkbox");
            //        if (vals.Contains(item))
            //        {
            //            builder.MergeAttribute("checked", "checked");
            //        }
            //        builder.MergeAttribute("value", item);
            //        builder.MergeAttribute("class", className);
            //        builder.MergeAttribute("onclick", clickAction);
            //        builder.MergeAttribute("name", className);
            //        builder.MergeAttribute("id", className);
            //        nobr.InnerHtml = builder.ToString() + "<label style='" + labelstyle + "'>" + item + "</label>";
            //        html += nobr.ToString();
            //    }
            //}
            //catch
            //{
            //    TagBuilder nobr = new TagBuilder("nobr");
            //    foreach (var item in lists)
            //    {
            //        TagBuilder builder = new TagBuilder("input");
            //        builder.MergeAttribute("type", "checkbox");
            //        builder.MergeAttribute("value", item);
            //        builder.MergeAttribute("class", className);
            //        builder.MergeAttribute("onclick", clickAction);
            //        builder.MergeAttribute("name", className);
            //        builder.MergeAttribute("id", className);
            //        nobr.InnerHtml = builder.ToString() + "<label style='" + labelstyle + "'>" + item + "</label>";
            //        html += nobr.ToString();
            //    }
            //}
            //TagBuilder builder1 = new TagBuilder("input");
            //builder1.MergeAttribute("type", "hidden");
            //if (metadata.IsRequired)
            //{
            //    builder1.MergeAttribute("data-val-required", "*");
            //    builder1.MergeAttribute("data-val", "true");
            //}
            //if (metadata.Model != null)
            //{
            //    builder1.MergeAttribute("value", metadata.Model.ToString());
            //}
            //builder1.MergeAttribute("name", metadata.PropertyName);
            //builder1.MergeAttribute("id", metadata.PropertyName);
            //html += builder1.ToString();
            //MvcHtmlString mhs = new MvcHtmlString(html);
            //return mhs;
            ModelMetadata metadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);
            IEnumerable<SelectListItem> lists = (IEnumerable<SelectListItem>)(htmlHelper.ViewContext.Controller.ViewData[metadata.PropertyName]);
            string html = "";
            IDictionary<string, object> attrs = htmlHelper.GetUnobtrusiveValidationAttributes(ExpressionHelper.GetExpressionText(expression), metadata);
            try
            {
                string[] vals = metadata.Model.ToString().Split(',');
                TagBuilder nobr = new TagBuilder("nobr");
                foreach (var item in lists)
                {
                    TagBuilder builder = new TagBuilder("input");
                    builder.MergeAttribute("type", "checkbox");
                    if (vals.Contains(item.Value))
                    {
                        builder.MergeAttribute("checked", "checked");
                    }
                    builder.MergeAttribute("value", item.Value);
                    builder.MergeAttribute("name", metadata.PropertyName);
                    builder.MergeAttribute("id", metadata.PropertyName);
                    builder.MergeAttributes<string, object>(attrs);
                    nobr.InnerHtml = builder.ToString() + "<label class=\"" + labelClass + "\">" + item.Value + "</label>";
                    html += nobr.ToString();
                }
            }
            catch
            {
                TagBuilder nobr = new TagBuilder("nobr");
                foreach (var item in lists)
                {
                    TagBuilder builder = new TagBuilder("input");
                    builder.MergeAttribute("type", "checkbox");
                    builder.MergeAttribute("value", item.Value);
                    builder.MergeAttribute("name", metadata.PropertyName);
                    builder.MergeAttribute("id", metadata.PropertyName);
                    builder.MergeAttributes<string, object>(attrs);
                    nobr.InnerHtml = builder.ToString() + "<label class=\"" + labelClass + "\">" + item.Value + "</label>";
                    html += nobr.ToString();
                }
            }
            MvcHtmlString mhs = new MvcHtmlString(html);
            return mhs;
        }

        public static MvcHtmlString CheckBoxListFor<TModel>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, String>> expression, IEnumerable<string> lists, string labelstyle)
        {
            ModelMetadata metadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);
            string className = Guid.NewGuid().ToString();
            string clickAction = "setCheckBoxListValue('" + className + "', '" + metadata.PropertyName + "')";
            string html = "";
            try
            {
                string[] vals = metadata.Model.ToString().Split(',');
                TagBuilder nobr = new TagBuilder("nobr");
                foreach (var item in lists)
                {
                    TagBuilder builder = new TagBuilder("input");
                    builder.MergeAttribute("type", "checkbox");
                    if (vals.Contains(item))
                    {
                        builder.MergeAttribute("checked", "checked");
                    }
                    builder.MergeAttribute("value", item);
                    builder.MergeAttribute("class", className);
                    builder.MergeAttribute("onclick", clickAction);
                    builder.MergeAttribute("name", className);
                    builder.MergeAttribute("id", className);
                    nobr.InnerHtml = builder.ToString() + "<label style='" + labelstyle + "'>" + item + "</label>";
                    html += nobr.ToString();
                }
            }
            catch
            {
                TagBuilder nobr = new TagBuilder("nobr");
                foreach (var item in lists)
                {
                    TagBuilder builder = new TagBuilder("input");
                    builder.MergeAttribute("type", "checkbox");
                    builder.MergeAttribute("value", item);
                    builder.MergeAttribute("class", className);
                    builder.MergeAttribute("onclick", clickAction);
                    builder.MergeAttribute("name", className);
                    builder.MergeAttribute("id", className);
                    nobr.InnerHtml = builder.ToString() + "<label style='" + labelstyle + "'>" + item + "</label>";
                    html += nobr.ToString();
                }
            }
            TagBuilder builder1 = new TagBuilder("input");
            builder1.MergeAttribute("type", "hidden");
            if (metadata.IsRequired)
            {
                builder1.MergeAttribute("data-val-required", "*");
                builder1.MergeAttribute("data-val", "true");
            }
            if (metadata.Model != null)
            {
                builder1.MergeAttribute("value", metadata.Model.ToString());
            }
            builder1.MergeAttribute("name", metadata.PropertyName);
            builder1.MergeAttribute("id", metadata.PropertyName);
            html += builder1.ToString();
            MvcHtmlString mhs = new MvcHtmlString(html);
            return mhs;
        }

        public static MvcHtmlString CheckBoxListFor<TModel>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, String>> expression, IEnumerable<string> lists, string errorMessage, string other, Expression<Func<TModel, String>> expressionOther, string labelstyle)
        {
            ModelMetadata metadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);
            ModelMetadata metadataOther = ModelMetadata.FromLambdaExpression(expressionOther, htmlHelper.ViewData);
            string otherPropertyName = metadataOther.PropertyName;
            string className = Guid.NewGuid().ToString();
            string clickAction = "setCheckBoxListValue('" + className + "', '" + metadata.PropertyName + "','" + other + "','" + metadataOther.PropertyName + "');";
            string html = "";
            bool othershow = false;
            try
            {
                string[] vals = metadata.Model.ToString().Split(',');
                if (vals.Contains(other))
                {
                    othershow = true;
                }
                TagBuilder nobr = new TagBuilder("nobr");
                foreach (var item in lists)
                {
                    TagBuilder builder = new TagBuilder("input");
                    builder.MergeAttribute("type", "checkbox");
                    if (vals.Contains(item))
                    {
                        builder.MergeAttribute("checked", "checked");
                    }
                    builder.MergeAttribute("value", item);
                    builder.MergeAttribute("class", className);
                    if (item == other)
                    {
                        builder.MergeAttribute("onclick", clickAction);
                    }
                    else
                    {
                        builder.MergeAttribute("onclick", clickAction);
                    }
                    builder.MergeAttribute("name", className);
                    builder.MergeAttribute("id", className);
                    if (item != other)
                    {
                        nobr.InnerHtml = builder.ToString() + "<label style='" + labelstyle + "'>" + item + "</label>";
                    }
                    else
                    {
                        nobr.InnerHtml = builder.ToString() + item;
                    }
                    html += nobr.ToString();
                }
            }
            catch
            {
                TagBuilder nobr = new TagBuilder("nobr");
                foreach (var item in lists)
                {
                    TagBuilder builder = new TagBuilder("input");
                    builder.MergeAttribute("type", "checkbox");
                    builder.MergeAttribute("value", item);
                    builder.MergeAttribute("class", className);
                    if (item == other)
                    {
                        builder.MergeAttribute("onclick", clickAction);
                    }
                    else
                    {
                        builder.MergeAttribute("onclick", clickAction);
                    }
                    builder.MergeAttribute("name", className);
                    builder.MergeAttribute("id", className);
                    if (item != other)
                    {
                        nobr.InnerHtml = builder.ToString() + "<label style='" + labelstyle + "'>" + item + "</label>";
                    }
                    else
                    {
                        nobr.InnerHtml = builder.ToString() + item;
                    }
                    html += nobr.ToString();
                }
            }
            TagBuilder builder1 = new TagBuilder("input");
            builder1.MergeAttribute("type", "hidden");
            if (metadata.IsRequired)
            {
                builder1.MergeAttribute("data-val-required", errorMessage);
                builder1.MergeAttribute("data-val", "true");
            }
            if (metadata.Model != null)
            {
                builder1.MergeAttribute("value", metadata.Model.ToString());
            }
            builder1.MergeAttribute("name", metadata.PropertyName);
            builder1.MergeAttribute("id", metadata.PropertyName);
            html += builder1.ToString();

            TagBuilder builder2 = new TagBuilder("input");
            builder2.MergeAttribute("type", "text");
            if (metadataOther.IsRequired)
            {
                builder2.MergeAttribute("data-val-required", errorMessage);
                builder2.MergeAttribute("data-val", "true");
            }
            if (metadataOther.Model != null)
            {
                builder2.MergeAttribute("value", metadataOther.Model.ToString());
            }
            else
            {
                builder2.MergeAttribute("value", "#Empty#");
            }
            builder2.MergeAttribute("name", otherPropertyName);
            if (!othershow)
            {
                builder2.MergeAttribute("style", "display: none;");
            }
            builder2.MergeAttribute("id", otherPropertyName);
            html += builder2.ToString();

            TagBuilder builder3 = new TagBuilder("span");
            builder3.MergeAttribute("class", "field-validation-valid");
            builder3.MergeAttribute("data-valmsg-replace", "true");
            builder3.MergeAttribute("data-valmsg-for", otherPropertyName);
            html += builder3.ToString();
            MvcHtmlString mhs = new MvcHtmlString(html);
            return mhs;
        }

        public static MvcHtmlString CheckBoxListFor<TModel>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, String>> expression, IEnumerable<string> lists, string errorMessage, string other, Expression<Func<TModel, String>> expressionOther, string labelstyle, string otherInputstyle)
        {
            ModelMetadata metadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);
            ModelMetadata metadataOther = ModelMetadata.FromLambdaExpression(expressionOther, htmlHelper.ViewData);
            string otherPropertyName = metadataOther.PropertyName;
            string className = Guid.NewGuid().ToString();
            string clickAction = "setCheckBoxListValue('" + className + "', '" + metadata.PropertyName + "','" + other + "','" + metadataOther.PropertyName + "');";
            string html = "";
            bool othershow = false;
            try
            {
                string[] vals = metadata.Model.ToString().Split(',');
                if (vals.Contains(other))
                {
                    othershow = true;
                }
                TagBuilder nobr = new TagBuilder("nobr");
                foreach (var item in lists)
                {
                    TagBuilder builder = new TagBuilder("input");
                    builder.MergeAttribute("type", "checkbox");
                    if (vals.Contains(item))
                    {
                        builder.MergeAttribute("checked", "checked");
                    }
                    builder.MergeAttribute("value", item);
                    builder.MergeAttribute("class", className);
                    if (item == other)
                    {
                        builder.MergeAttribute("onclick", clickAction);
                    }
                    else
                    {
                        builder.MergeAttribute("onclick", clickAction);
                    }
                    builder.MergeAttribute("name", className);
                    builder.MergeAttribute("id", className);
                    if (item != other)
                    {
                        nobr.InnerHtml = builder.ToString() + "<label style='" + labelstyle + "'>" + item + "</label>";
                    }
                    else
                    {
                        nobr.InnerHtml = builder.ToString() + item;
                    }
                    html += nobr.ToString();
                }
            }
            catch
            {
                TagBuilder nobr = new TagBuilder("nobr");
                foreach (var item in lists)
                {
                    TagBuilder builder = new TagBuilder("input");
                    builder.MergeAttribute("type", "checkbox");
                    builder.MergeAttribute("value", item);
                    builder.MergeAttribute("class", className);
                    if (item == other)
                    {
                        builder.MergeAttribute("onclick", clickAction);
                    }
                    else
                    {
                        builder.MergeAttribute("onclick", clickAction);
                    }
                    builder.MergeAttribute("name", className);
                    builder.MergeAttribute("id", className);
                    if (item != other)
                    {
                        nobr.InnerHtml = builder.ToString() + "<label style='" + labelstyle + "'>" + item + "</label>";
                    }
                    else
                    {
                        nobr.InnerHtml = builder.ToString() + item;
                    }
                    html += nobr.ToString();
                }
            }
            TagBuilder builder1 = new TagBuilder("input");
            builder1.MergeAttribute("type", "hidden");
            if (metadata.IsRequired)
            {
                builder1.MergeAttribute("data-val-required", errorMessage);
                builder1.MergeAttribute("data-val", "true");
            }
            if (metadata.Model != null)
            {
                builder1.MergeAttribute("value", metadata.Model.ToString());
            }
            builder1.MergeAttribute("name", metadata.PropertyName);
            builder1.MergeAttribute("id", metadata.PropertyName);
            html += builder1.ToString();

            TagBuilder builder2 = new TagBuilder("input");
            builder2.MergeAttribute("type", "text");
            if (metadataOther.IsRequired)
            {
                builder2.MergeAttribute("data-val-required", errorMessage);
                builder2.MergeAttribute("data-val", "true");
            }
            if (metadataOther.Model != null)
            {
                builder2.MergeAttribute("value", metadataOther.Model.ToString());
            }
            else
            {
                builder2.MergeAttribute("value", "#Empty#");
            }
            builder2.MergeAttribute("name", otherPropertyName);
            if (!othershow)
            {
                builder2.MergeAttribute("style", "display: none;" + otherInputstyle);
            }
            else
            {
                builder2.Attributes.Add("style", otherInputstyle);
            }
            builder2.MergeAttribute("id", otherPropertyName);
            html += builder2.ToString();

            TagBuilder builder3 = new TagBuilder("span");
            builder3.MergeAttribute("class", "field-validation-valid");
            builder3.MergeAttribute("data-valmsg-replace", "true");
            builder3.MergeAttribute("data-valmsg-for", otherPropertyName);
            html += builder3.ToString();
            MvcHtmlString mhs = new MvcHtmlString(html);
            return mhs;
        }
        #endregion

        #region Html.RadioListFor [4 overrides]

        public static MvcHtmlString BitRadioListFor<TModel>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, String>> expression, string truetext = "是", string falsetext = "否", string labelClass = "radiolabel")
        {
            ModelMetadata metadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);
            List<SelectListItem> list = new List<SelectListItem>();
            SelectListItem slitrue = new SelectListItem();
            slitrue.Text = truetext;
            slitrue.Value = "true";
            SelectListItem slifalse = new SelectListItem();
            slifalse.Text = falsetext;
            slifalse.Value = "false";
            list.Add(slitrue);
            list.Add(slifalse);
            htmlHelper.ViewData[metadata.PropertyName] = list.AsEnumerable();
            return htmlHelper.RadioListFor(expression);
        }

        public static MvcHtmlString RadioListFor<TModel>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, String>> expression, string labelClass = "radiolabel")
        {
            ModelMetadata metadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);
            IEnumerable<SelectListItem> lists = (IEnumerable<SelectListItem>)(htmlHelper.ViewData[metadata.PropertyName]);
            IDictionary<string, object> attrs = htmlHelper.GetUnobtrusiveValidationAttributes(ExpressionHelper.GetExpressionText(expression), metadata);
            string html = "";
            try
            {
                string[] vals = metadata.Model.ToString().Split(',');
                TagBuilder nobr = new TagBuilder("nobr");
                foreach (var item in lists)
                {
                    TagBuilder builder = new TagBuilder("input");
                    builder.MergeAttribute("type", "radio");
                    if (vals.Contains(item.Value))
                    {
                        builder.MergeAttribute("checked", "checked");
                    }
                    builder.MergeAttribute("value", item.Value);
                    builder.MergeAttribute("name", metadata.PropertyName);
                    builder.MergeAttribute("id", metadata.PropertyName);
                    builder.MergeAttributes<string, object>(attrs);
                    nobr.InnerHtml = builder.ToString() + "<label class=\"" + labelClass + "\">" + item.Text + "</label>";
                    html += nobr.ToString();
                }
            }
            catch
            {
                TagBuilder nobr = new TagBuilder("nobr");
                foreach (var item in lists)
                {
                    TagBuilder builder = new TagBuilder("input");
                    builder.MergeAttribute("type", "radio");
                    builder.MergeAttribute("value", item.Value);
                    builder.MergeAttribute("name", metadata.PropertyName);
                    builder.MergeAttribute("id", metadata.PropertyName);
                    builder.MergeAttributes<string, object>(attrs);
                    nobr.InnerHtml = builder.ToString() + "<label class=\"" + labelClass + "\">" + item.Text + "</label>";
                    html += nobr.ToString();
                }
            }
            MvcHtmlString mhs = new MvcHtmlString(html);
            return mhs;
        }

        public static MvcHtmlString RadioListFor<TModel>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, String>> expression, IEnumerable<string> lists, string labelstyle)
        {
            ModelMetadata metadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);
            string className = Guid.NewGuid().ToString();
            string clickAction = "setRadioListValue('" + className + "', '" + metadata.PropertyName + "')";
            string html = "";
            try
            {
                string[] vals = metadata.Model.ToString().Split(',');
                TagBuilder nobr = new TagBuilder("nobr");
                foreach (var item in lists)
                {
                    TagBuilder builder = new TagBuilder("input");
                    builder.MergeAttribute("type", "radio");
                    if (vals.Contains(item))
                    {
                        builder.MergeAttribute("checked", "checked");
                    }
                    builder.MergeAttribute("value", item);
                    builder.MergeAttribute("class", className);
                    builder.MergeAttribute("onclick", clickAction);
                    builder.MergeAttribute("name", className);
                    builder.MergeAttribute("id", className);
                    nobr.InnerHtml = builder.ToString() + "<label style='" + labelstyle + "'>" + item + "</label>";
                    html += nobr.ToString();
                }
            }
            catch
            {
                TagBuilder nobr = new TagBuilder("nobr");
                foreach (var item in lists)
                {
                    TagBuilder builder = new TagBuilder("input");
                    builder.MergeAttribute("type", "radio");
                    builder.MergeAttribute("value", item);
                    builder.MergeAttribute("class", className);
                    builder.MergeAttribute("onclick", clickAction);
                    builder.MergeAttribute("name", className);
                    builder.MergeAttribute("id", className);
                    nobr.InnerHtml = builder.ToString() + "<label style='" + labelstyle + "'>" + item + "</label>";
                    html += nobr.ToString();
                }
            }
            TagBuilder builder1 = new TagBuilder("input");
            builder1.MergeAttribute("type", "hidden");
            if (metadata.IsRequired)
            {
                builder1.MergeAttribute("data-val-required", "*");
                builder1.MergeAttribute("data-val", "true");
            }
            if (metadata.Model != null)
            {
                builder1.MergeAttribute("value", metadata.Model.ToString());
            }
            builder1.MergeAttribute("name", metadata.PropertyName);
            builder1.MergeAttribute("id", metadata.PropertyName);
            html += builder1.ToString();
            MvcHtmlString mhs = new MvcHtmlString(html);
            return mhs;
        }

        public static MvcHtmlString RadioListFor<TModel>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, String>> expression, IEnumerable<string> lists, string errorMessage, string other, Expression<Func<TModel, String>> expressionOther, string labelstyle)
        {
            ModelMetadata metadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);
            ModelMetadata metadataOther = ModelMetadata.FromLambdaExpression(expressionOther, htmlHelper.ViewData);
            string otherPropertyName = metadataOther.PropertyName;
            string className = Guid.NewGuid().ToString();
            string clickAction = "setRadioListValue('" + className + "', '" + metadata.PropertyName + "');";
            string hideAction = "$('#" + otherPropertyName + "').hide();";
            string showAction = "$('#" + otherPropertyName + "').show();";
            string html = "";
            bool othershow = false;
            try
            {
                string[] vals = metadata.Model.ToString().Split(',');
                if (vals.Contains(other))
                {
                    othershow = true;
                }
                TagBuilder nobr = new TagBuilder("nobr");
                foreach (var item in lists)
                {
                    TagBuilder builder = new TagBuilder("input");
                    builder.MergeAttribute("type", "radio");
                    if (vals.Contains(item))
                    {
                        builder.MergeAttribute("checked", "checked");
                    }
                    builder.MergeAttribute("value", item);
                    builder.MergeAttribute("class", className);
                    if (item == other)
                    {
                        builder.MergeAttribute("onclick", clickAction + showAction);
                    }
                    else
                    {
                        builder.MergeAttribute("onclick", clickAction + hideAction);
                    }
                    builder.MergeAttribute("name", className);
                    builder.MergeAttribute("id", className);
                    if (item != other)
                    {
                        nobr.InnerHtml = builder.ToString() + "<label style='" + labelstyle + "'>" + item + "</label>";
                    }
                    else
                    {
                        nobr.InnerHtml = builder.ToString() + item;
                    }
                    html += nobr.ToString();
                }
            }
            catch
            {
                TagBuilder nobr = new TagBuilder("nobr");
                foreach (var item in lists)
                {
                    TagBuilder builder = new TagBuilder("input");
                    builder.MergeAttribute("type", "radio");
                    builder.MergeAttribute("value", item);
                    builder.MergeAttribute("class", className);
                    if (item == other)
                    {
                        builder.MergeAttribute("onclick", clickAction + showAction);
                    }
                    else
                    {
                        builder.MergeAttribute("onclick", clickAction + hideAction);
                    }
                    builder.MergeAttribute("name", className);
                    builder.MergeAttribute("id", className);
                    if (item != other)
                    {
                        nobr.InnerHtml = builder.ToString() + "<label style='" + labelstyle + "'>" + item + "</label>";
                    }
                    else
                    {
                        nobr.InnerHtml = builder.ToString() + item;
                    }
                    html += nobr.ToString();
                }
            }
            TagBuilder builder1 = new TagBuilder("input");
            builder1.MergeAttribute("type", "hidden");
            if (metadata.IsRequired)
            {
                builder1.MergeAttribute("data-val-required", errorMessage);
                builder1.MergeAttribute("data-val", "true");
            }
            if (metadata.Model != null)
            {
                builder1.MergeAttribute("value", metadata.Model.ToString());
            }
            builder1.MergeAttribute("name", metadata.PropertyName);
            builder1.MergeAttribute("id", metadata.PropertyName);
            html += builder1.ToString();

            TagBuilder builder2 = new TagBuilder("input");
            builder2.MergeAttribute("type", "text");
            if (metadataOther.IsRequired)
            {
                builder2.MergeAttribute("data-val-required", errorMessage);
                builder2.MergeAttribute("data-val", "true");
            }
            if (metadataOther.Model != null)
            {
                builder2.MergeAttribute("value", metadataOther.Model.ToString());
            }
            else
            {
                builder2.MergeAttribute("value", "#Empty#");
            }
            builder2.MergeAttribute("name", otherPropertyName);
            if (!othershow)
            {
                builder2.MergeAttribute("style", "display: none;");
            }
            builder2.MergeAttribute("id", otherPropertyName);
            html += builder2.ToString();

            TagBuilder builder3 = new TagBuilder("span");
            builder3.MergeAttribute("class", "field-validation-valid");
            builder3.MergeAttribute("data-valmsg-replace", "true");
            builder3.MergeAttribute("data-valmsg-for", otherPropertyName);
            html += builder3.ToString();
            MvcHtmlString mhs = new MvcHtmlString(html);
            return mhs;
        }

        public static MvcHtmlString RadioListFor<TModel>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, String>> expression, IEnumerable<string> lists, string errorMessage, string other, Expression<Func<TModel, String>> expressionOther, string labelstyle, string otherInputstyle)
        {
            ModelMetadata metadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);
            ModelMetadata metadataOther = ModelMetadata.FromLambdaExpression(expressionOther, htmlHelper.ViewData);
            string otherPropertyName = metadataOther.PropertyName;
            string className = Guid.NewGuid().ToString();
            string clickAction = "setRadioListValue('" + className + "', '" + metadata.PropertyName + "');";
            string hideAction = "$('#" + otherPropertyName + "').hide();";
            string showAction = "$('#" + otherPropertyName + "').show();";
            string html = "";
            bool othershow = false;
            try
            {
                string[] vals = metadata.Model.ToString().Split(',');
                if (vals.Contains(other))
                {
                    othershow = true;
                }
                TagBuilder nobr = new TagBuilder("nobr");
                foreach (var item in lists)
                {
                    TagBuilder builder = new TagBuilder("input");
                    builder.MergeAttribute("type", "radio");
                    if (vals.Contains(item))
                    {
                        builder.MergeAttribute("checked", "checked");
                    }
                    builder.MergeAttribute("value", item);
                    builder.MergeAttribute("class", className);
                    if (item == other)
                    {
                        builder.MergeAttribute("onclick", clickAction + showAction);
                    }
                    else
                    {
                        builder.MergeAttribute("onclick", clickAction + hideAction);
                    }
                    builder.MergeAttribute("name", className);
                    builder.MergeAttribute("id", className);
                    if (item != other)
                    {
                        nobr.InnerHtml = builder.ToString() + "<label style='" + labelstyle + "'>" + item + "</label>";
                    }
                    else
                    {
                        nobr.InnerHtml = builder.ToString() + item;
                    }
                    html += nobr.ToString();
                }
            }
            catch
            {
                TagBuilder nobr = new TagBuilder("nobr");
                foreach (var item in lists)
                {
                    TagBuilder builder = new TagBuilder("input");
                    builder.MergeAttribute("type", "radio");
                    builder.MergeAttribute("value", item);
                    builder.MergeAttribute("class", className);
                    if (item == other)
                    {
                        builder.MergeAttribute("onclick", clickAction + showAction);
                    }
                    else
                    {
                        builder.MergeAttribute("onclick", clickAction + hideAction);
                    }
                    builder.MergeAttribute("name", className);
                    builder.MergeAttribute("id", className);
                    if (item != other)
                    {
                        nobr.InnerHtml = builder.ToString() + "<label style='" + labelstyle + "'>" + item + "</label>";
                    }
                    else
                    {
                        nobr.InnerHtml = builder.ToString() + item;
                    }
                    html += nobr.ToString();
                }
            }
            TagBuilder builder1 = new TagBuilder("input");
            builder1.MergeAttribute("type", "hidden");
            if (metadata.IsRequired)
            {
                builder1.MergeAttribute("data-val-required", errorMessage);
                builder1.MergeAttribute("data-val", "true");
            }
            if (metadata.Model != null)
            {
                builder1.MergeAttribute("value", metadata.Model.ToString());
            }
            builder1.MergeAttribute("name", metadata.PropertyName);
            builder1.MergeAttribute("id", metadata.PropertyName);
            html += builder1.ToString();

            TagBuilder builder2 = new TagBuilder("input");
            builder2.MergeAttribute("type", "text");
            builder2.MergeAttribute("style", otherInputstyle);
            if (metadataOther.IsRequired)
            {
                builder2.MergeAttribute("data-val-required", errorMessage);
                builder2.MergeAttribute("data-val", "true");
            }
            if (metadataOther.Model != null)
            {
                builder2.MergeAttribute("value", metadataOther.Model.ToString());
            }
            else
            {
                builder2.MergeAttribute("value", "#Empty#");
            }
            builder2.MergeAttribute("name", otherPropertyName);
            if (!othershow)
            {
                builder2.MergeAttribute("style", "display: none;" + otherInputstyle);
            }
            else
            {
                builder2.Attributes.Add("style", otherInputstyle);
            }
            builder2.MergeAttribute("id", otherPropertyName);
            html += builder2.ToString();

            TagBuilder builder3 = new TagBuilder("span");
            builder3.MergeAttribute("class", "field-validation-valid");
            builder3.MergeAttribute("data-valmsg-replace", "true");
            builder3.MergeAttribute("data-valmsg-for", otherPropertyName);
            html += builder3.ToString();
            MvcHtmlString mhs = new MvcHtmlString(html);
            return mhs;
        }
        #endregion

        #region Html.DropDownListFor(x => x.field)
        public static MvcHtmlString DropDownListFor<TModel>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, String>> expression, string optionLabel = "-请选择-", bool allowMultiple = false)
        {
            ModelState state;
            ModelMetadata metadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);
            IEnumerable<SelectListItem> lists = (IEnumerable<SelectListItem>)(htmlHelper.ViewContext.Controller.ViewData[metadata.PropertyName]);
            //return htmlHelper.DropDownListFor(expression, lists, optionlabel);
            StringBuilder builder = new StringBuilder();
            if (optionLabel != null)
            {
                SelectListItem item2 = new SelectListItem();
                item2.Text = optionLabel;
                item2.Value = string.Empty;
                item2.Selected = false;
                builder.AppendLine(ListItemToOption(item2));
            }
            foreach (SelectListItem item3 in lists)
            {
                builder.AppendLine(ListItemToOption(item3));
            }
            TagBuilder builder3 = new TagBuilder("select");
            builder3.InnerHtml = builder.ToString();
            TagBuilder tagBuilder = builder3;
            //tagBuilder.MergeAttributes<string, object>(htmlAttributes);
            tagBuilder.MergeAttribute("name", metadata.PropertyName, true);
            tagBuilder.GenerateId(metadata.PropertyName);
            if (allowMultiple)
            {
                tagBuilder.MergeAttribute("multiple", "multiple");
            }
            if (htmlHelper.ViewData.ModelState.TryGetValue(metadata.PropertyName, out state) && (state.Errors.Count > 0))
            {
                tagBuilder.AddCssClass(HtmlHelper.ValidationInputCssClassName);
            }
            tagBuilder.MergeAttributes<string, object>(htmlHelper.GetUnobtrusiveValidationAttributes(metadata.PropertyName));
            return new MvcHtmlString(tagBuilder.ToString());
        }
        #endregion

        public static string ListItemToOption(SelectListItem item)
        {
            TagBuilder builder2 = new TagBuilder("option");
            builder2.InnerHtml = HttpUtility.HtmlEncode(item.Text);
            TagBuilder builder = builder2;
            if (item.Value != null)
            {
                builder.Attributes["value"] = item.Value;
            }
            if (item.Selected)
            {
                builder.Attributes["selected"] = "selected";
            }
            return builder.ToString(TagRenderMode.Normal);
        }

        #region Html.CheckBoxFor(x => x.field)
        public static MvcHtmlString CheckBoxFor<TModel>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, Boolean?>> expression)
        {
            ModelMetadata metadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);
            string className = "defaultCheckBox";
            string html = "";
            try
            {
                bool vals = (bool)metadata.Model;
                TagBuilder builder = new TagBuilder("input");
                builder.MergeAttribute("type", "checkbox");
                if (vals)
                {
                    builder.MergeAttribute("checked", "checked");
                }
                builder.MergeAttribute("class", className);
                builder.MergeAttribute("name", metadata.PropertyName);
                builder.MergeAttribute("id", metadata.PropertyName);
                builder.MergeAttribute("value", "true");
                if (metadata.IsRequired)
                {
                    builder.MergeAttribute("data-val-required", "*");
                    builder.MergeAttribute("data-val", "true");
                }
                html += builder.ToString();
            }
            catch
            {
                TagBuilder builder = new TagBuilder("input");
                builder.MergeAttribute("type", "checkbox");
                builder.MergeAttribute("class", className);
                builder.MergeAttribute("name", metadata.PropertyName);
                builder.MergeAttribute("id", metadata.PropertyName);
                builder.MergeAttribute("value", "true");
                if (metadata.IsRequired)
                {
                    builder.MergeAttribute("data-val-required", "*");
                    builder.MergeAttribute("data-val", "true");
                }
                html += builder.ToString();
            }
            MvcHtmlString mhs = new MvcHtmlString(html);
            return mhs;
        }
        #endregion

        #region Html.List(Model)
        public static List<dynamic> List<TModel>(this HtmlHelper<TModel> Html, IndexView Model, string ItemClass = "item", string AltClass = "alt")
        {
            Html.ViewContext.TempData["alt"] = true;
            Html.ViewContext.TempData["css"] = AltClass;
            return Model.items;
        }
        #endregion
        #region Html.SortLink(text, column, Model, upstr, downstr, defstr)
        public static MvcHtmlString SortLink<TModel>(this HtmlHelper<TModel> Html, string linkText, string columnName, IndexView Model, string upArrowString = "&uarr;", string downArrowString = "&darr;", string defaultArrowString = "&nbsp;")
        {
            string trail = defaultArrowString;
            if (Model.order == columnName)
            {
                if (!Model.desc)
                    trail = upArrowString;
                else
                    trail = downArrowString;
            }
            var desc = Model.order == columnName ? !Model.desc : true;
            return new MvcHtmlString(Html.ActionLink(linkText, null, new { o = columnName, d = desc ? 1 : 0, q = Model.query }).ToString() + trail);
        }
        #endregion
        #region Html.Alt()
        public static MvcHtmlString Alt<TModel>(this HtmlHelper<TModel> Html)
        {
            var TempData = Html.ViewContext.TempData;
            if (TempData["alt"] == null)
            {
                throw new Exception("ALT must be in LISTVIEW control");
            }
            string AltClass = TempData["css"].ToString();
            bool alt = !(bool)TempData["alt"];
            TempData["alt"] = alt;
            if (alt) return new MvcHtmlString(AltClass);
            else return new MvcHtmlString("");
        }
        #endregion
        #region Html.Pager(Model)
        public static MvcHtmlString Pager<TModel>(this HtmlHelper<TModel> Html, IndexView Model, PageType type = PageType.Typical)
        {
            if (Model.page.count <= 0)
            {
                return new MvcHtmlString("&gt; &gt; 没有数据 &lt; &lt;");
            }
            else
            {
                StringBuilder sbHtml = new StringBuilder();

                if (type == PageType.Numeric)
                {
                    sbHtml.Append(PageLink<TModel>(Html, Model, "上一页", Model.page.index - 1, Model.page.index <= 0));
                    sbHtml.Append(" ");
                    for (int i = Math.Max(0, Model.page.index - 4); i <= Math.Min(Model.page.page - 1, Model.page.index + 4); i++)
                    {
                        sbHtml.Append(PageLink<TModel>(Html, Model, (i + 1).ToString(), i, Model.page.index == i));
                        sbHtml.Append(" ");
                    }
                    sbHtml.Append(PageLink<TModel>(Html, Model, "下一页", Model.page.index + 1, Model.page.index >= Model.page.page - 1));
                }
                else
                {
                    bool sDisabled = Model.page.index <= 0;
                    bool eDisabled = Model.page.index + 1 >= Model.page.page;

                    sbHtml.Append(PageLink<TModel>(Html, Model, "首页", 0, sDisabled));
                    sbHtml.Append(" ");
                    sbHtml.Append(PageLink<TModel>(Html, Model, "上一页", Model.page.index - 1, sDisabled));
                    sbHtml.Append(" ");
                    sbHtml.Append(PageLink<TModel>(Html, Model, "下一页", Model.page.index + 1, eDisabled));
                    sbHtml.Append(" ");
                    sbHtml.AppendLine(PageLink<TModel>(Html, Model, "尾页", Model.page.page - 1, eDisabled));

                    sbHtml.AppendFormat(" [ {0} / {1} ] ", Model.page.index + 1, Model.page.page);
                    sbHtml.AppendLine();

                    sbHtml.AppendFormat(@"第<input id=""tb_goto"" name=""tb_goto"" size=""{0}"" maxlength=""{0}"" />页",
                        (int)Math.Log10(Model.page.page) + 1);
                    sbHtml.AppendLine();
                    sbHtml.AppendFormat(@"<button id=""btn_goto"" name=""btn_goto"" type=""button"" onclick=""return page_check($('#tb_goto').val(), {0});"">跳转</button>", Model.page.page);
                    sbHtml.AppendLine();
                }

                return new MvcHtmlString(sbHtml.ToString());
            }
        }

        private static string PageLink<TModel>(HtmlHelper<TModel> Html, IndexView Model, string Text, int index, bool disabled = false)
        {
            if (disabled)
            {
                return string.Format("<a disabled>{0}</a>", Text); ;
            }
            else
            {
                return Html.ActionLink(Text, "Index", new { p = index, o = Model.order, d = Model.desc ? 1 : 0, q = Model.query }).ToString();
            }
        }
        #endregion

        #region Html.CommonnScript(Model)
        public static MvcHtmlString CommonnScript<TModel>(this HtmlHelper<TModel> Html, IndexView Model = null)
        {
            var selectURL = System.Configuration.ConfigurationManager.AppSettings["UserSelectServer"] + "HttpHandlers/UserChooser.aspx";
            var TempData = Html.ViewContext.TempData;
            StringBuilder sbHtml = new StringBuilder("<script type='text/javascript'>");
            if (TempData["__ErrorMessage"] != null)
            {
                sbHtml.AppendFormat("alert('{0}');", TempData["__ErrorMessage"]);
            }
            var route = Html.RouteCollection.GetRouteData(Html.ViewContext.RequestContext.HttpContext);
            sbHtml.AppendFormat("var MVC={{DetailUrl:'{0}',IndexUrl:'{1}',CreateUrl:'{2}',EditUrl:'{3}',Action:'{4}',Controller:'{5}',SelectUrl:'{6}'}};",
                Html.ActionUrl("Details"),
                Html.ActionUrl("Index", (Model != null ? new { o = Model.order, d = Model.desc ? 1 : 0, q = Model.query } : null)),
                Html.ActionUrl("Create"),
                Html.ActionUrl("Edit"),
                route.Values["action"].ToString().ToLower(),
                route.Values["controller"].ToString().ToLower(),
                selectURL);
            if (TempData["__CloseWindow"] != null)
            {
                sbHtml.Append("CloseWindow();");
            }
            sbHtml.Append("</script>");
            sbHtml.Append(Html.Hidden("mvc_command").ToString());
            sbHtml.Append(Html.Hidden("mvc_args").ToString());
            return new MvcHtmlString(sbHtml.ToString());
        }
        #endregion

        public static void ShowMessage(this Controller controller, string message)
        {
            controller.TempData["__ErrorMessage"] = message;
        }

        public static void CloseWindow(this Controller controller)
        {
            controller.TempData["__CloseWindow"] = true;
        }

        public static string ActionUrl<TModel>(this HtmlHelper<TModel> Html, string action, dynamic args = null)
        {
            if (args == null)
                return UrlHelper.GenerateUrl("Default", action, null, null, Html.RouteCollection, Html.ViewContext.RequestContext, true);
            else
                return UrlHelper.GenerateUrl("Default", action, null, new RouteValueDictionary(args), Html.RouteCollection, Html.ViewContext.RequestContext, true);
        }

        public static string Eval(dynamic val, dynamic format = null, string defaultVal = "")
        {
            if (val == null)
                return defaultVal;

            if (val is string)
            {
                int cnt;
                if (int.TryParse(format, out cnt))
                    return CutString(val, cnt);
                else
                    return val;
            }

            Type t = val.GetType();

            MethodInfo method = t.GetMethod("ToString", new Type[] { typeof(string) });
            object res;
            if (method == null)
            {
                method = t.GetMethod("ToString", new Type[] { });
                res = method.Invoke(val, new object[] { });
            }
            else
            {
                res = method.Invoke(val, new object[] { format });
            }

            if (res == null) return defaultVal;
            return res.ToString();
        }

        private static string CutString(string title, int count)
        {
            if (title == null)
                return null;
            int len = count * 2;
            if (len <= 0) return title;

            string str = title;

            int curIdx = 0;
            int curLen = 0;
            int cutIdx = 0;
            int cutLen = 0;
            int inc = 0;
            for (int i = 0; i < str.Length; i++)
            {
                inc = str[i] > (char)255 ? 2 : 1;
                curIdx++;
                curLen += inc;
                if (curLen > len - 3)
                {
                    if (cutIdx == 0)
                    {
                        cutIdx = curIdx - 1;
                        cutLen = curLen - inc;
                    }
                    if (curLen > len)
                    {
                        if (cutLen == len - 3)
                            return str.Substring(0, cutIdx) + "...";
                        else return str.Substring(0, cutIdx) + " ...";
                    }
                }
            }
            return str;
        }
    }
    public enum PageType
    {
        Typical, Numeric
    }
}